package com.bestcem.xm.common.core.uitls;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.Set;

/**
 * @author ming.xue <ming.xue@idiaoyan.com>
 * @desc JSON 工具类
 * @date 2021-07-24
 */
@Slf4j
public class JsonUtil {

    /**
     * 默认
     */
    private static final ObjectMapper mapper = new ObjectMapper();

    /**
     * 下划线
     */
    private static final ObjectMapper snakeMapper = new ObjectMapper();

    static {
        // 反序列化的时候如果多了其他属性,不抛出异常
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        snakeMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // 如果是空对象的时候,不抛异常
        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        snakeMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

        // 序列化忽略null
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        snakeMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // 下划线
        snakeMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
    }

    /**
     * 对象转为Json字符串
     *
     * @param data 对象
     * @return Json字符串
     */
    public static String transferToJson(Object data) {
        String jsonStr = null;
        try {
            jsonStr = mapper.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            log.error("transferToJson fail", e);
        }
        return jsonStr;
    }

    /**
     * json字符串转为指定类型
     *
     * @param str           json字符串
     * @param typeReference 类型
     * @return 对象
     */
    public static <T> T jsonToTransfer(String str, TypeReference<T> typeReference) {
        T data = null;
        try {
            data = mapper.readValue(str, typeReference);
        } catch (IOException e) {
            log.error("jsonToTransfer fail", e);
        }
        return data;
    }

    /**
     * 对象转为Json字符串(下划线)
     *
     * @param data 对象
     * @return Json字符串
     */
    public static String transferToJsonSnake(Object data) {
        String jsonStr = null;
        try {
            jsonStr = snakeMapper.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            log.error("transferToJson fail", e);
        }
        return jsonStr;
    }

    /**
     * 对象转为指定类型(下划线)
     *
     * @param data          对象
     * @param typeReference 指定类型
     * @param <T>           类型
     * @return 指定类型对象
     */
    public static <T> T convertValueSnake(Object data, TypeReference<T> typeReference) {
        return snakeMapper.convertValue(data, typeReference);
    }

    /**
     * 尝试将Java对象转换为JSON字符串
     *
     * @param obj
     * @return
     */
    public static String tryConvertToJSONString(Object obj) {
        if (obj == null) {
            return null;
        }

        String result = null;
        try {
            result = JSONObject.toJSONString(obj);
        } catch (Exception e) {
            log.error("try convert to JSONString failed, obj: {}", obj, e);
        }
        return result;
    }

    /**
     * 尝试将Java对象转换为JSON对象
     *
     * @param obj
     * @return
     */
    public static JSONObject tryConvertToJSONObject(Object obj) {
        if (obj == null) {
            return null;
        }

        JSONObject result = null;
        try {
            if (obj.getClass().equals(String.class)) {
                result = JSONObject.parseObject(String.valueOf(obj));
            } else {
                String objStr = JSONObject.toJSONString(obj);
                result = JSONObject.parseObject(objStr);
            }
        } catch (Exception e) {
            log.error("try convert to JSONObject failed, obj: {}", obj, e);
        }
        return result;
    }

    /**
     * 尝试将字符串转换为JSON对象
     *
     * @param jsonStr
     * @return
     */
    public static JSONObject tryConvertToJSONObject(String jsonStr) {
        if (StringUtils.isBlank(jsonStr)) {
            return null;
        }

        JSONObject result = null;
        try {
            result = JSONObject.parseObject(jsonStr);
        } catch (Exception e) {
            log.error("parse jsonStr failed, jsonStr: {}", jsonStr, e);
        }
        return result;
    }

    /**
     * 将 JSONObject 的 item 组装成 JSONArray 的item
     *
     * @param jsonObject
     * @return
     */
    public static JSONArray jsonObjectToJsonArray(JSONObject jsonObject) {
        JSONArray array = new JSONArray();
        if (!jsonObject.isEmpty()) {
            Set<String> keys = jsonObject.keySet();
            keys.forEach(key -> {
                JSONObject object = new JSONObject();
                object.put(key, jsonObject.get(key));
                array.add(object);
            });
        }
        return array;
    }
}
